package tcp_helper

import (
	"encoding/binary"
	"math"
)

/*
	消息格式：
	固定头 消息id长度(uint16) 消息id 消息体长度(uint32) 消息体
*/

const fixed_head = "XTP" // 固定头

type Package struct {
	Id   []byte //消息id, 作为消息来源的标志
	Data []byte //消息体, 存放数据, 可加密
}
type PackageLst []*Package

func CreatePackage(id, data []byte) *Package {
	return &Package{id, data}
}

func (p *Package) Serialize() []byte {
	buf := []byte(fixed_head)

	id_len := len(p.Id)
	if id_len > math.MaxUint16 {
		panic("package serialize failed: id is too long")
	}
	buf = append(buf, 0, 0)
	binary.BigEndian.PutUint16(buf[len(buf)-2:], uint16(id_len))

	buf = append(buf, p.Id...)

	buf = append(buf, 0, 0, 0, 0)
	binary.BigEndian.PutUint32(buf[len(buf)-4:], uint32(len(p.Data)))

	buf = append(buf, p.Data...)
	return buf
}

//解析一个字节串，返回解析到的包列表 和 剩下的字节串. 会改变入参
func UnSerializePackage(pbuffer *[]byte) PackageLst {

	const head_len = len(fixed_head)
	lst := make([]*Package, 0, 2)
	for {
		if len(*pbuffer) < head_len+2+4 {
			return lst
		}

		has_head, _ := skipToHead(pbuffer)
		if !has_head {
			return lst
		}

		var id_len uint16 = binary.BigEndian.Uint16((*pbuffer)[head_len : head_len+2])
		if len(*pbuffer) < head_len+2+int(id_len)+4 {
			return lst
		}

		pck := new(Package)
		pck.Id = (*pbuffer)[head_len+2 : head_len+2+int(id_len)]

		var data_len uint32 = binary.BigEndian.Uint32((*pbuffer)[head_len+2+int(id_len) : head_len+2+int(id_len)+4])
		total_len := head_len + 2 + int(id_len) + 4 + int(data_len)
		if len(*pbuffer) < total_len {
			return lst
		}

		pck.Data = (*pbuffer)[head_len+2+int(id_len)+4 : total_len]
		*pbuffer = append((*pbuffer)[:0], (*pbuffer)[total_len:]...)
		lst = append(lst, pck)
	}
}

//调到head处，返回： 是否找到head, 是否发生跳动. 会改变入参
func skipToHead(pbuffer *[]byte) (has_head bool, has_skip bool) {
	const head_len = len(fixed_head)
	head_bytes := []byte(fixed_head)
	index := 0
	for ; index <= len(*pbuffer)-head_len; index += 1 {

		is_equal := true
		for i := 0; i < head_len; i += 1 {
			if head_bytes[i] != (*pbuffer)[index+i] {
				is_equal = false
				break
			}
		}

		if is_equal {
			*pbuffer = append((*pbuffer)[:0], (*pbuffer)[index:]...) //删除index之前的元素
			return true, index != 0
		}
	}

	if len(*pbuffer) >= head_len {
		*pbuffer = append((*pbuffer)[:0], (*pbuffer)[index+1:]...)
		return false, true
	} else {
		return false, false
	}
}

/*
测试代码：
func main() {

	t := [2]byte{0, 0}
	p := t[1:]
	p[0] = 1

	pk := new(Package)
	pk.Id = []byte("id")
	pk.Data = []byte("data")
	ret := pk.Serialize()
	ret = append([]byte{0, 0}, ret...)
	ret = append(ret, 3,4)

	lst := UnSerializePackage(&ret)

	fmt.Println(ret, lst)
}
*/
